import json
import time
import uuid
from django import http
from django.http import JsonResponse, HttpResponseForbidden
from django.shortcuts import render
from django.views import View
from carts.models import Carts
from tools.response_code import RETCODE
from user.models import Address
from decimal import Decimal
from orders.models import OrderInfo,OrderGoods
from goods.models import SKU
import  logging
logger = logging.getLogger('django')
# 导入事务包
from django.db import transaction

class OrderSettlement(View):
    '''结算订单界面'''
    def get(self,request):
        # 请求数据 收货地址，购物车勾选商品  总金额 payment_amount,运费 freight，商品总数量，total_count
        # 筛选出当前用户的未删除的地址列表
        addresses = Address.objects.filter(user=request.user,is_deleted=False)
        # 筛选出当前用户购物车中勾选的未删除的所有商品
        cart_goods = Carts.objects.filter(user=request.user,selected=True,is_delete=False)
        total_count = 0 # 通过查询集的count方法可以直接计算出一个查询集中元素的数量
        total_amount = 0 # 定义总金额的变量，初始化为 0
        for goods in cart_goods:
            # 商品的小计 = 当前商品的价格 * 当前商品的数量 临时的给每一种商品增加一个小计的属性
            goods.amount = goods.count * goods.sku.price
            # 将商品的数量乘以价格，累加到总金额中
            total_amount += goods.amount
            # 将商品的数量累加到商品总数量中
            total_count += goods.count
        # 给每一单增加10元运费
        freight = Decimal('10.00')
        # 最后计算总金额  = 所有商品的合计+运费
        payment_amount = freight + total_amount
        # 返回页面，返回数据
        return render(request,'place_order.html',locals())


class OrderCommit(View):
    '''  提交订单 保存订单的信息，和订单商品'''

    def post(self,request):
        # 获取前端通过ajax传过来的json
        json_dict = json.loads(request.body.decode())
        address_id=json_dict.get('address_id')
        pay_method= int(json_dict.get('pay_method'))
        # 校验数据
        if not all([address_id,pay_method]):
            return http.HttpResponseForbidden('缺少必要的参数')
        if not Address.objects.filter(id=address_id).exists():
            return http.HttpResponseForbidden('参数address_id不正确')
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'],OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return http.HttpResponseForbidden('参数pay_method不正确')
        # 准备订单的基本信息
        order_id = uuid.uuid4().hex
        status =''
        if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID'] #如果支付方式是支付宝 则显示待支付
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND'] #如果支付方式是货到付款 待发货
        with transaction.atomic():
            # 设置一个事务的保存点
            save_id = transaction.savepoint()
            try:
                # 在order_info 表中创建一个不完整的订单
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    total_count=0,
                    total_amount=Decimal('0'),
                    freight= Decimal('10.00'),
                    pay_method=pay_method,
                    address_id=address_id,
                    user=request.user,
                    status=status

                )
                while True:
                    # 处理本次订单的所有商品 商品来自于购物车中选中的商品
                    cart_skus = Carts.objects.filter(user=request.user,selected=True,is_delete=False)
                    for cart_sku in cart_skus:

                        sku = cart_sku.sku #sku 就是购物车中这款商品对应的sku表中的某一个具体商品
                        # 求出本次订单中这个商品的数量
                        buy_count = cart_sku.count
                        # 判断一下库存够不够
                        if buy_count > sku.stock:
                            # 库存不足啊
                            # 之前创建的订单也不能保存了,需要做事务回滚
                            transaction.savepoint_rollback(save_id)
                            return JsonResponse({'code':RETCODE.STOCKERR,'errmsg':'库存不足'})

                        # 遍历商品，将商品的数量和金额累加到 order_info表中
                        order.total_count += buy_count
                        order.total_amount += (buy_count * sku.price)
                        order.save()
                        # 修改sku表中的库存和销量
                        # 求出原来的库存和销量
                        old_stock = sku.stock
                        old_sales = sku.sales
                        # time.sleep(5)
                        # 算出最新的库存和销量
                        new_stock = old_stock - buy_count
                        new_sales = old_sales + buy_count
                        # # 保存修改
                        # sku.stock = new_stock
                        # sku.sales = new_sales
                        # sku.save()
                        # 使用乐观锁防止并发购买，超购的现象出现
                        result= SKU.objects.filter(id=sku.id,stock=old_stock).update(stock=new_stock,sales=new_sales)
                        if result == 0:
                            #出现了并发的状态需要重新进行提交订单
                            continue
                        # 修改并保存spu中销量
                        sku.spu.sales += buy_count
                        sku.spu.save()
                        # 将本商品添加到order_goods,
                        OrderGoods.objects.create(count=buy_count,price=sku.price,order=order,sku=sku)
                    # 将所有商品的金额累加到总金额以后，再加上本单的运费
                    order.total_amount += order.freight
                    order.save()
                    # 购买成功后，也就是将order—info 、order_goods 保存完毕后 ，还需要删除购物车中对应的商品
                    Carts.objects.filter(user=request.user, selected=True, is_delete=False).update(is_delete=True)
                    return JsonResponse({'code': RETCODE.OK, 'errmsg': '下单成功', 'order_id': order_id})


            except Exception as e:
                print(e)
                # 事务回滚
                transaction.savepoint_rollback(save_id)
                return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '下单失败'})

                # # 提交事务
                # transaction.savepoint_commit(save_id)


class OrderSuccess(View):
    '''订单成功界面'''
    def get(self,request):
        order_id = request.GET.get('order_id')
        payment_amount = request.GET.get('payment_amount')
        pay_method = request.GET.get('pay_method')

        try:
            ret = OrderInfo.objects.filter(order_id=order_id,pay_method=pay_method)
        except Exception as e:
            print(e)
            return http.HttpResponseForbidden('订单参数错误')
        return render(request,'order_success.html',locals())


class OrderComment(View):
    '''订单评价功能'''
    def get(self,request):
        # 获取数据，请求的查询字符串
        order_id = request.GET.get('order_id')
        order_goods = OrderGoods.objects.filter(order_id=order_id,is_commented=False)
        # 按照前端页面要求，定义一个空列表，用来存储订单中所有的商品
        uncomment_goods_list = []
        # 遍历skus 组合前端需要的数据
        for goods in order_goods:
            uncomment_goods_list.append({
                'order_id':goods.order_id,
                'sku_id':goods.sku.id,
                'name':goods.sku.name,
                'price':str(goods.sku.price),
                'score':goods.score,
                'default_image_url':'/static/images/goods/'+goods.sku.default_image.url+'.jpg',
            })

        return render(request,'goods_judge.html',locals())

    def post(self,request):
        '''接收评价数据，并且保存到数据库中'''
        json_dict = json.loads(request.body.decode())
        order_id=json_dict.get('order_id')
        sku_id=json_dict.get('sku_id')
        comment=json_dict.get('comment')
        score=json_dict.get('score')
        is_anonymous=json_dict.get('is_anonymous')
        # 校验数据
        if not all([order_id,sku_id,comment,score]):
            return JsonResponse({'code':RETCODE.NECESSARYPARAMERR,'errmsg':'缺少必传的参数'})
        oid_exist = OrderInfo.objects.filter(order_id=order_id,user=request.user,status=OrderInfo.ORDER_STATUS_ENUM['UNCOMMENT']).exists()
        sid_exist = SKU.objects.filter(id=sku_id).exists()
        if not sid_exist or not oid_exist:
            return HttpResponseForbidden('参数错误')
        if is_anonymous: # 布尔值 其他的值
            if not isinstance(is_anonymous,bool):
                # 如果数据进到这个代码段，说明is_anonymous 不是一个布尔值
                return HttpResponseForbidden('参数错误')

        # 保存数据 Order_goods sku spu
        OrderGoods.objects.filter(order_id=order_id,sku_id=sku_id,is_commented=False).update(
            comment = comment,
            score = score,
            is_anonymous = is_anonymous,
            is_commented = True
        )
        try:
            sku = SKU.objects.get(id = sku_id)
        except SKU.DoesNotExist as  e :
            logger.error('sku_id不正确')
        #修改sku表中的数据
        sku.comments +=1
        sku.save()
        # 修改spu表中的数据
        sku.spu.comments += 1
        sku.spu.save()
        # 还需要把Order——goods表中对应的商品，状态改成已完成
        if OrderGoods.objects.filter(order_id=order_id,is_commented=False).count() == 0:
            # 说明我们这个订单中所有的商品都被评价过了
            OrderInfo.objects.filter(order_id=order_id).update(status = OrderInfo.ORDER_STATUS_ENUM['FINISHED'])


        return JsonResponse({'code':RETCODE.OK,'errmsg':'OK'})